home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 37 / Amiga Format CD37 (1999-02-16)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-03].iso / -screenplay- / shareware / invasionforce / source / cyber_interface.c < prev    next >
C/C++ Source or Header  |  1999-01-09  |  16KB  |  508 lines

  1. /*
  2. AI Code for Invasion Force - an Explore/Conquer Strategic Wargame
  3. Copyright (C) 1996  Brannen Hough
  4.  
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. /*
  20.     cyber_interface.c -- artificial intelligence module for Empire II
  21.  
  22. */
  23.  
  24. /* This file contains all the routines associated with interfacing 
  25.     with the main game engine - basically at two places (1) selecting
  26.     production for new cities (and cities that just built something)
  27.     and (2) the player's mainloop (where all the units get moved, etc.)
  28.     Cleanup (when the game is over) has also been stuck in here. 
  29. */
  30.  
  31. #include "global.h"
  32.  
  33. #define  DEBUG_AI_INT(string)  if (!rtEZRequestTags(string,"Continue|Abort", \
  34.      NULL,NULL, RTEZ_Flags,EZREQF_CENTERTEXT,RT_Window,map_window, \
  35.      RT_ReqPos,REQPOS_CENTERWIN,RT_LockWindow,TRUE,TAG_END )) \
  36.      { if (AIhandle != NULL)  unpost_it(AIhandle); AIhandle = NULL; \
  37.      clean_exit(0, NULL); }
  38.  
  39. /***************************************************************
  40. *************** Production Interface   *************************
  41. ***************************************************************/
  42.  
  43. /* This routine will set up the needed production for all Governors. */
  44. void  set_automated_production (struct City *metro)
  45. {
  46.     int     AI_type = PLAYER.aggr;
  47.     struct  GovNode*  Gov = NULL;
  48.  
  49.    /* Now let's explore the hex we start with.  If we just took this
  50.        city, or are starting out with it, this is important. */
  51.     explore_at_hex(player,metro->col,metro->row,INVISIBLE,FALSE);
  52.  
  53.     /* We do the next in this manner so that other computer opponents
  54.        can be added later, up to the ten maximum. Note we have deliberate
  55.        fall-throughs so that unsupported AI types will default to the 
  56.        'best' supported type. */
  57.     switch( AI_type ) {
  58.     case 10:
  59.     case 9:
  60.     case 8:
  61.     case 7:
  62.     case 6:
  63.     case 5:
  64.         //Gov = AI4_locate_gov( metro );
  65.         /* Let the Gov take a look around */
  66.         //explore_at_hex( player, metro->col, metro->row, INVISIBLE, FALSE);
  67.         //AI1_do_one_histogram( Gov );
  68.         //AI5_set_gov_mode( Gov );
  69.         //AI5_set_gov_prod( metro, Gov );
  70.         //if( PLAYER.aggr != 5 ) PLAYER.aggr = 5;
  71.         //break;
  72.     case 4:
  73.         Gov = AI4_locate_gov( metro );
  74.         /* And let the (perhaps new) Gov take a look around */
  75.         explore_at_hex( player, metro->col, metro->row, INVISIBLE, FALSE);
  76.         AI1_do_one_histogram (Gov);
  77.         AI3_set_gov_mode (Gov);
  78.         AI4_set_gov_prod( metro, Gov );
  79.         if( PLAYER.aggr != 4 ) PLAYER.aggr = 4;
  80.         break;
  81.     case 3:
  82.         Gov = AI3_locate_gov( metro );
  83.         /* And let the (perhaps new) Gov take a look around */
  84.         explore_at_hex( player, metro->col, metro->row, INVISIBLE, FALSE);
  85.         AI1_do_one_histogram (Gov);
  86.         AI3_set_gov_mode (Gov);
  87.         AI3_set_gov_prod( metro, Gov );
  88.         if( PLAYER.aggr != 3 ) PLAYER.aggr = 3;
  89.         break;
  90.     //case 1:
  91.     case 2:
  92.         Gov = AI2_locate_gov( metro );
  93.         AI2_set_gov_prod( metro, Gov );
  94.         if( PLAYER.aggr != 2 ) PLAYER.aggr = 2;
  95.         break;
  96.     case 1:
  97.         Gov = AI1_locate_gov( metro );
  98.         AI1_set_gov_prod( metro, Gov );
  99.         if( PLAYER.aggr != 1 ) PLAYER.aggr = 1;
  100.         break;
  101.     default:
  102.         DEBUG_AI("Error in set_automated_prod.  Aggressiveness out of range.")
  103.         break;
  104.     } /* End switch */
  105.     return;
  106. }
  107.  
  108.  
  109. int    do_computer_city_production ()
  110. {
  111.     struct City *metro = (struct City *)city_list.mlh_Head;
  112.     int         ctr = 0;
  113.     /* This routine will duplicate much of do_cities_production.  These two
  114.         should be put back together in the future.  For now, this works just
  115.     fine. 
  116.     */
  117.  
  118.     for ( ; metro->cnode.mln_Succ; metro = 
  119.           (struct City *)metro->cnode.mln_Succ)
  120.       if (metro->owner==player) {
  121.          metro->unit_wip += (metro->industry*PLAYER.prod)/50;
  122.          explore_at_hex(player,metro->col,metro->row,INVISIBLE,TRUE); 
  123.          if (metro->unit_wip >= wishbook[metro->unit_type].build) {
  124.          /* We finished a new unit */
  125.          make_new_unit( metro );
  126.          /* Now we call set_automated_production to set a new production
  127.         for this city 
  128.         */
  129.          ctr++;
  130.          set_automated_production (metro);
  131.          } /* End if > Wishbook */
  132.       } /* End if owner of city */
  133.     /* End for loop */
  134.  
  135.     return (ctr);  /* Don't know if this is usefull info or not right now. */
  136. }
  137.  
  138.  
  139. void   make_new_unit( struct City* metro)
  140. {
  141.     struct GovNode *Gov = NULL;
  142.     struct GovNode *Gov2 = NULL;
  143.     int            Done;
  144.  
  145.     struct Unit *new_unit = AllocVec((int)sizeof(*new_unit),MEMF_CLEAR);
  146.  
  147.     metro->unit_wip = 0;
  148.  
  149.     /* build the unit */
  150.     new_unit->col = metro->col;
  151.     new_unit->row = metro->row;
  152.     new_unit->owner = player;
  153.     new_unit->type = metro->unit_type;
  154.     new_unit->move = unit_speed(new_unit);
  155.     new_unit->damage = 0;
  156.     new_unit->attacks = 0;
  157.     new_unit->cargo = 0;
  158.     new_unit->ship = NULL;
  159.     new_unit->orders = NULL;
  160.     new_unit->fuel = wishbook[new_unit->type].range;
  161.     
  162.     /* DEBUG_AI("Built new unit!") */
  163.  
  164.     /* We need to name the unit so that we can tell what governor 
  165.        owns it. This is done to keep within the unit structures
  166.        as defined and not add any more elements (so far).
  167.        */
  168.     Done = 0;
  169.     if( (new_unit->type == TRANSPORT) || (new_unit->type == CARRIER) ||
  170.     (new_unit->type == BATTLESHIP) ) {
  171.         // These units get their own Governor
  172.         struct GovNode *new_gov = AllocVec((int)sizeof(*new_gov),MEMF_CLEAR);
  173.  
  174.     new_gov->x = metro->col;
  175.     new_gov->y = metro->row;
  176.     new_gov->targx = -1;
  177.     new_gov->targy = -1;
  178.     new_gov->searchx = -1;
  179.     new_gov->searchy = -1;
  180.     new_gov->mode = GOV_SEARCH;
  181.     new_gov->flags = 0;
  182.     new_gov->owner = player;
  183.     if( new_unit->type == TRANSPORT ) new_gov->type = GOV_TRANSPORT;
  184.     if( new_unit->type == CARRIER )  new_gov->type = GOV_CARRIER;
  185.     if( new_unit->type == BATTLESHIP )  new_gov->type = GOV_BATTLESHIP;
  186.     new_gov->ID = NewGov++;
  187.     // Add a random number to keep from revealing too much to human
  188.     //   players
  189.     NewGov += (int) RangeRand(3L);
  190.  
  191.     // Note: The AI must initialize this Governor before using it -
  192.     //   it has not had do_one_histogram or set_gov_mode done on it.
  193.     //   These functions are AI dependent, so they are not done here.
  194.  
  195.     /*sprintf (outbuf, "Creating Governor %ld at %ld,%ld",
  196.          new_gov->ID, new_gov->x, new_gov->y);
  197.     DEBUG_AI(outbuf) */
  198.     
  199.     /* Add the new governor to the list of governors */
  200.     AddTail((struct List *)&GovList,(struct Node *)new_gov);
  201.  
  202.     sprintf( outbuf, "%ld / %ld", new_gov->ID, NewUnit++);
  203.     // Add a random number to keep from revealing too much to human
  204.     //   players
  205.     NewUnit += (int) RangeRand(6L);
  206.     name_unit( new_unit, outbuf );
  207.     }
  208.     else {
  209.       for ( Gov = (struct GovNode *)GovList.mlh_Head; (Gov->gnode.mln_Succ) 
  210.           && (!Done); Gov = (struct GovNode *)Gov->gnode.mln_Succ) {
  211.     /* Check for the right coordinates */
  212.     if ((Gov->x == metro->col) && (Gov->y == metro->row)
  213.         && (Gov->owner == player)
  214.         && ((Gov->type == GOV_CITY) || (Gov->type == GOV_PORT)
  215.         || (Gov->type == GOV_ISLAND) )) {
  216.             /* We found the right governor, now let's
  217.             set the name correctly
  218.             */
  219.             sprintf (outbuf, "%ld / %ld", Gov->req.req_gov, NewUnit++);
  220.         // Add a random number to keep from revealing too much to human
  221.         //   players
  222.         NewUnit += (int) RangeRand(6L);
  223.         name_unit(new_unit, outbuf);
  224.             Done = 1;
  225.             sprintf(outbuf, "Built new %s", UnitString[new_unit->type]);
  226.         DEBUG_AI(outbuf)
  227.             sprintf(outbuf, "Naming unit '%s' (%ld)", new_unit->name,
  228.                 Gov->req.req_gov);
  229.         DEBUG_AI(outbuf)
  230.         /* And, lets update the data for the owning governor */
  231.         for(Gov2 = (struct GovNode *)GovList.mlh_Head;
  232.             (Gov2->gnode.mln_Succ);
  233.             Gov2 = (struct GovNode *)Gov2->gnode.mln_Succ) {
  234.           if( Gov2->ID == Gov->req.req_gov ) {
  235.             Gov2->hist.TotalMyUnits++;
  236.             Gov2->hist.UnitCounts[new_unit->type]++;
  237.           }
  238.         } /* end for */
  239.         } /* End if right coordinates and owner */
  240.       }  /* End for loop */
  241.     } // End else another type of unit
  242.     if ((!Done) || (new_unit->name == NULL)) {
  243.     name_unit(new_unit, "UNNAMED");
  244.     DEBUG_AI("Problem! Have no name for newly built unit")
  245.     if (!Done) DEBUG_AI("Did not find correct Governor")
  246.     sprintf (outbuf, "%s Unit %s is at %ld, %ld",
  247.          UnitString[new_unit->type], new_unit->name, new_unit->col,
  248.          new_unit->row);
  249.     DEBUG_AI(outbuf)
  250.     }
  251.     AddTail((struct List *)&unit_list,(struct Node *)new_unit);
  252. }
  253.  
  254.  
  255.  
  256. /*************************************************************
  257. ***************  Game Play Routines  *************************
  258. *************************************************************/
  259.  
  260. void  computer_player_moves ()
  261. {
  262.     int          AI_type = PLAYER.aggr;
  263.     int          new_units;
  264.     struct Unit *unit = (struct Unit *)unit_list.mlh_Head;
  265.     struct Unit *FoundUnit = (struct Unit *)unit_list.mlh_Head;
  266.     struct City *FoundCity = (struct City *)city_list.mlh_Head;
  267.  
  268.     /* This routine is called by the game mechanics to do the computer
  269.         player's moves, production, repair, etc.
  270.     */
  271.  
  272.  
  273.     /* First, let's put up the appropriate msg to say who we are */
  274.     switch( AIDataFlag ) {
  275.       case 5:
  276.         // Show the AI players moving
  277.         PLAYER.show = SHOW_GRP;
  278.         PLAYER.soundfx = SOUND_NONE;
  279.         // Find a unit or city owned by the player
  280.         while( (FoundCity->cnode.mln_Succ) && (FoundCity->owner != player) )
  281.             FoundCity = (struct City *)FoundCity->cnode.mln_Succ;
  282.         if( !FoundCity->cnode.mln_Succ ) FoundCity = NULL;
  283.         while( (FoundUnit->unode.mln_Succ) && (FoundUnit->owner != player) )
  284.             FoundUnit = (struct Unit *)FoundUnit->unode.mln_Succ;
  285.         if( !FoundUnit->unode.mln_Succ ) FoundUnit = NULL;
  286.         // Create a map display there
  287.         if( FoundCity )  create_player_display( FoundCity->col, 
  288.             FoundCity->row );
  289.         if( FoundUnit )  create_player_display( FoundUnit->row,
  290.             FoundUnit->col );
  291.         // Deliberate fall-through
  292.       case 4:
  293.         // Set the message delay to 30
  294.         PLAYER.msg_delay = 30;
  295.         // Deliberate fall-through
  296.       case 3:
  297.         // Set the message delay to 20
  298.         if( AIDataFlag < 4 ) {
  299.             PLAYER.msg_delay = 20;
  300.         }
  301.         // Add the sticky note
  302.         sprintf (outbuf, "Player %ld (AI type %ld)", 
  303.              player, AI_type);
  304.         AIhandle = post_it (outbuf);
  305.         // Deliberate fall-through
  306.       case 2:
  307.         // Add a tell_user call
  308.         sprintf (outbuf, "Player %ld (AI type %ld)", 
  309.              player, AI_type);
  310.         tell_user2( outbuf, FALSE, NULL );
  311.         // Deliberate fall-through
  312.       case 1: {
  313.         if( AIDataFlag < 3 ) {
  314.             // Set the message delay to 10
  315.             PLAYER.msg_delay = 10;
  316.         }
  317.         if( AIDataFlag < 5 ) {
  318.             PLAYER.show = SHOW_NON;
  319.         }
  320.            // Show a wait cursor
  321.         SetPointer(map_window,BUSY_POINTER);
  322.         break;
  323.       }
  324.       default: {
  325.         PLAYER.msg_delay = 10;
  326.         PLAYER.show = SHOW_NON;    
  327.         break;
  328.       }
  329.     } // End switch
  330.  
  331.     /* update all unit moves and explore around units */
  332.     for (; unit->unode.mln_Succ; unit = (struct Unit *)unit->unode.mln_Succ)
  333.          if (unit->owner==player) {
  334.             unit->move = unit_speed(unit);
  335.             unit->attacks = 0;
  336.             explore_at_hex(player,unit->col,unit->row,INVISIBLE,FALSE); 
  337.          } /* End if my units */
  338.     /* End For Loop */
  339.     /* DEBUG_AI("Updated all units movement points") */
  340.  
  341.     /* update his production for this turn */
  342.     new_units = do_computer_city_production();
  343.     /* DEBUG_AI("Done with production phase") */
  344.  
  345.     /* We do the next in this manner so that other computer opponents
  346.        can be added later, up to the ten maximum. Note we have deliberate
  347.        fall-throughs so that unsupported AI types will default to the 
  348.        'best' supported type. */
  349.     switch( AI_type ) {
  350.     case 10:
  351.     case 9:
  352.     case 8:
  353.     case 7:
  354.     case 6:
  355.     case 5:
  356.         //AI5_play_turn( new_units );
  357.         //break;
  358.     case 4:
  359.         AI4_play_turn( new_units );
  360.         break;
  361.     case 3:
  362.         AI3_play_turn( new_units );
  363.         break;
  364.     //case 1:
  365.     case 2:
  366.         AI2_play_turn( new_units );
  367.         break;
  368.     case 1:
  369.         New_AI1_play_turn( new_units );
  370.         break;
  371.     default:
  372.         DEBUG_AI("Error in computer_player_moves().  Aggressiveness out of range.")
  373.         break;
  374.     } /* End switch */
  375.  
  376.     
  377.     /* do some housekeeping at end of turn
  378.        here I want to check for any ships that need repair
  379.        */
  380.     unit=(struct Unit *)unit_list.mlh_Head;
  381.     for (; unit->unode.mln_Succ; unit=(struct Unit *)unit->unode.mln_Succ)
  382.          if (unit->damage > 0 && unit->move > 50)
  383.             if (unit->owner==player && city_hereP(unit->col,unit->row))
  384.                unit->damage--;
  385.     /* End if, End if, End for */
  386.     /* DEBUG_AI("Done with unit repair") */
  387.  
  388.  
  389.     /* All Done.  Let's remove the sticky note */
  390.     switch( AIDataFlag ) {
  391.       case 5:
  392.         // Hide the AI players moving
  393.         roster[player].show = SHOW_NON;
  394.         // Deliberate fall-through
  395.       case 4:
  396.         // Deliberate fall-through
  397.       case 3:
  398.         // Deliberate fall-through
  399.         // Remove the sticky note
  400.         unpost_it(AIhandle);
  401.         AIhandle = NULL;
  402.       case 2:
  403.         // Deliberate fall-through
  404.         // Nothing to do here
  405.       case 1: {
  406.         // Remove the wait cursor
  407.         ClearPointer( map_window );
  408.         break;
  409.       }
  410.       default: {
  411.         break;
  412.       }
  413.     } // End switch
  414.  
  415.     return;
  416. }
  417.  
  418. /*************************************************************
  419. *************** Initialization and Cleanup *******************
  420. *************************************************************/
  421.  
  422. // This routine is to deallocate the memory for computer opponents
  423. void    cleanup_computer()
  424. {
  425.     //calc_move (MOVE_CLEANUP, NULL, 0, 0, 0, 0);
  426.  
  427.     // We need to clean out and delete all the Governors
  428.     nuke_list (&GovList);
  429.  
  430.     // Take out Post-it if up
  431.     if (AIhandle != NULL)  unpost_it(AIhandle);
  432.     AIhandle = NULL;
  433.  
  434.     // And just for the heck of it, reset the numbering scheme
  435.     NewGov = 12;
  436.     NewUnit = 1000;
  437.  
  438.     return;
  439. }
  440.  
  441.  
  442. /*************************************************************
  443. ***************  Saving and Restoring Files  *****************
  444. *************************************************************/
  445.  
  446.  
  447. int  SaveAIPlayers( BPTR file, char* err )
  448. {
  449.   // the governor list
  450.    {
  451.       struct GovNode *gov = ( struct GovNode* ) GovList.mlh_Head;
  452.       int num_govs = count_nodes( &GovList );
  453.  
  454.       Write( file, &num_govs, (long) sizeof( num_govs ) );
  455.       for (; gov->gnode.mln_Succ; gov = ( struct GovNode* )gov->gnode.mln_Succ)
  456.          // We want to save everything in each governor node except the cnode
  457.          // so that has to stay in the front, and this needs to point to the
  458.          // first item of data AFTER the cnode, which is the type for the
  459.          // governors
  460.          Write( file, &gov->type, (long)(sizeof( *gov )-sizeof(gov->gnode)) );
  461.    }
  462.  
  463.   return 0;
  464. }
  465.  
  466.  
  467. int  LoadAIPlayers( BPTR file, char*err )
  468. {
  469.    int  ctr;
  470.  
  471.    // restore the AI players' governors list
  472.    int num_govs;
  473.  
  474.    (void)Read( file, &num_govs, sizeof( num_govs ) );
  475.    if ( num_govs > 0 ) {
  476.       struct GovNode *gov;
  477.  
  478.       for( ctr=1; ctr <= num_govs; ctr++ ) {
  479.          gov = AllocVec( sizeof( *gov ), MEMF_CLEAR );
  480.          if ( gov == NULL ) {
  481.             strcpy( err, "Unable to allocate RAM for governors." );
  482.             return -1;
  483.          } // end if
  484.          (void)Read( file, &gov->type, sizeof( *gov )- sizeof( gov->gnode ));
  485.          AddTail( (struct List* )&GovList, (struct Node *)gov );
  486.      } // End for
  487.    } // end if
  488.    return 0;
  489. }
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.